#include <APFFNDR.H>
#include <APGCLI.H>
#include <aknmessagequerydialog.h>

#include <AknConsts.h>
#include <Avkon.mbg>

#include <MrLockUi.rsg>
#include "MrLock.hrh"

#include "Utils.h"
#include "AppListSettingPage.h"
#include "ApplicationDetailsDialog.h"

#include "Logger.h"

CAppListSettingPage::CAppListSettingPage(CSelectionItemList* aList, RArray<TUid>* aAppList, TBool aIncludeUtils)
:CAknCheckBoxSettingPage(R_CHECKLIST_SETPAGE, aList), iAppList(aAppList), iSelectionList(aList), iIncludeUtils(aIncludeUtils)
{

}

CAppListSettingPage::~CAppListSettingPage()
{
	if (iSelectionList)
	{
		iSelectionList->ResetAndDestroy();
		delete iSelectionList;
		iSelectionList = NULL;
	}
	iTempAppList.Close();
}

void AppendAppCaptionL(TDes& aName, TApaAppInfo& aAppInfo)
{
	TPtrC caption;
	if (aAppInfo.iCaption.Length() > 1)
		caption.Set(aAppInfo.iCaption);
	else if (aAppInfo.iShortCaption.Length() > 1)
		caption.Set(aAppInfo.iShortCaption);
	else if (aAppInfo.iFullName.Length() > 0)
	{
		TInt ind = aAppInfo.iFullName.LocateReverse('\\');
		caption.Set(aAppInfo.iFullName.Right(aAppInfo.iFullName.Length() - ind - 1));
	}
	aName.Append(caption.Left(25));
}

TUid RemoveUidL(TDes& aItemName)
{
	TInt pos = aItemName.LocateReverse(TChar('\t'));
	TBuf<30> uidBuf = aItemName.Mid(pos+3);
	TLex16 lex(uidBuf);
	TUint32 uidInt;
	lex.Val(uidInt, EHex);
	aItemName.Copy(aItemName.Left(pos));
	return TUid::Uid(uidInt);
}

CSelectionItemList* CAppListSettingPage::CreateSelectionListL()
{
	CSelectionItemList* list = new (ELeave) CSelectionItemList(10);
	return list;
}

CAppListSettingPage* CAppListSettingPage::NewL(const TDesC& aTitle, RArray<TUid>* aAppList, TInt aInd, TBool aIncludeUtils)
{
	CSelectionItemList* list = CreateSelectionListL();
	CAppListSettingPage * settingPage = new (ELeave) CAppListSettingPage(list, aAppList, aIncludeUtils);

	CleanupStack::PushL(settingPage);//+page
	if (aInd != KErrNotFound)
		settingPage->SetSettingNumberL(aInd+1);
	settingPage->SetSettingTextL(aTitle);
	CleanupStack::Pop();//-page
	return settingPage;
}

void CAppListSettingPage::AcceptSettingL()
{
	iAppList->Reset();
	CAknCheckBoxSettingPage::AcceptSettingL();
	for (TInt i = 0;i < iTempAppList.Count();i++)
		iAppList->Append(iTempAppList[i]);
}

void CAppListSettingPage::NextPageL(TInt aScroll)
{
	CAknSetStyleListBox* listBox = ListBoxControl();

	TInt itemIndex = Min(listBox->Model()->NumberOfItems()-1, Max(0, listBox->CurrentItemIndex()+aScroll));
	TInt topIndex = Min(listBox->Model()->NumberOfItems()-1, Max(0, listBox->TopItemIndex()+aScroll));

	listBox->SetTopItemIndex(topIndex );
	listBox->SetCurrentItemIndex(itemIndex);
	listBox->DrawNow();
}

void CAppListSettingPage::AddApplicationsL()
{
	TBuf<40> buf;
	buf.Format(_L("%S"), &Utils::GetR(R_TEXT_APPLICATIONS));
	CMySelectableItem* item = CMySelectableItem::NewL(buf, EFalse, TUid::Uid(200));
	iSelectionList->AppendL(item);
	if (iSettings.iShowApps)
		AddApplicationsL(EFalse);
	buf.Format(_L("%S"), &Utils::GetR(R_TEXT_HIDDEN_APPLICATIONS));
	item = CMySelectableItem::NewL(buf, EFalse, TUid::Uid(201));
	iSelectionList->AppendL(item);
	if (iSettings.iShowHiddenApps)
		AddApplicationsL(ETrue);

	SetSelectionItemArrayL(iSelectionList);
	UpdateListBoxL();
}

void CAppListSettingPage::AddApplicationsL(TBool aHidden)
{
	iSettings.iAppSortType = TAppListSettings::ESortByName;
	TBuf<50> itemName;
	RApaLsSession lsSession;
	lsSession.Connect();
	CleanupClosePushL(lsSession);//+lsSession
	lsSession.GetAllApps();
	TInt appCount = 0;
	lsSession.AppCount(appCount);
	TApaAppInfo appInfo;
	TApaAppCapabilityBuf capability;
	CDesCArrayFlat* arr = new (ELeave) CDesCArrayFlat(appCount+1);
	CleanupStack::PushL(arr);//+arr

	CDesCArrayFlat* arr2 = new (ELeave) CDesCArrayFlat(iTempAppList.Count()+1);
	CleanupStack::PushL(arr2);//+arr2
	TTime now;
	now.HomeTime();

	while (lsSession.GetNextApp(appInfo) == KErrNone)
	{
		lsSession.GetAppCapability(capability,appInfo.iUid);

		if (!aHidden == capability().iAppIsHidden)
		{
			continue;
		}

		itemName.Zero();
		if (iSettings.iAppSortType == TAppListSettings::ESortByDate)
		{
			TEntry appEntry;
			TTimeIntervalSeconds seconds = 1000000000;
			if (KErrNone == CEikonEnv::Static()->FsSession().Entry(appInfo.iFullName, appEntry))
				now.SecondsFrom(appEntry.iModified, seconds);
			itemName.Format(_L("%010d"), seconds.Int());
		}

		AppendAppCaptionL(itemName, appInfo);
		itemName.AppendFormat(_L("\t0x%08x"), appInfo.iUid.iUid);
		TBool marked = (KErrNotFound != iTempAppList.Find(appInfo.iUid));

		if (EFalse == marked)
		{
			arr->AppendL(itemName);
		}
		else
		{
			arr2->AppendL(itemName);
		}
	}

	for (TInt i = 0;i < arr2->Count();i++)
	{
		itemName.Copy(arr2->operator[](i));
		TUid appUid = RemoveUidL(itemName);

		if (iSettings.iAppSortType == TAppListSettings::ESortByDate)
			itemName.Copy(itemName.Mid(10));
		CMySelectableItem* item = CMySelectableItem::NewL(itemName, ETrue, appUid);
		iSelectionList->AppendL(item);
	}

	arr->Sort();

	for (TInt i = 0;i < arr->Count();i++)
	{
		itemName.Copy(arr->operator[](i));
		TUid appUid = RemoveUidL(itemName);
		if (iSettings.iAppSortType == TAppListSettings::ESortByDate)
			itemName.Copy(itemName.Mid(10));
		CMySelectableItem* item = CMySelectableItem::NewL(itemName, EFalse, appUid);
		iSelectionList->AppendL(item);
	}

	CleanupStack::PopAndDestroy();//-arr2
	CleanupStack::PopAndDestroy();//-arr
	CleanupStack::PopAndDestroy();//-lsSession
	SetSelectionItemArrayL(iSelectionList);
	UpdateListBoxL();
}

void UpdateAppListL(RArray<TUid>& aAppList, CMySelectableItem* aItem)
{
	TInt ind = aAppList.Find(aItem->iUid);
	if (aItem->SelectionStatus())
	{//selected, add
	 	if (ind == KErrNotFound)
			aAppList.Append(aItem->iUid);
	}
	else aAppList.Remove(ind);
}

void CAppListSettingPage::DeleteApplicationsL()
{
	TInt startInd = 0;
	for (;startInd < iSelectionList->Count();startInd++)
	{
		CMySelectableItem* item = (CMySelectableItem*) iSelectionList->operator[](startInd);	
		if (item->iUid.iUid == 200)
			break;
	}
	
	DeleteSelectionListL(startInd, iSelectionList->Count()-startInd);
}

void CAppListSettingPage::ShowPropertiesL()
{
	DeleteSelectionListL(0, 1);
	AddPropertiesStringL(EFalse);

	CMySelectableItem* secondItem = (CMySelectableItem*) iSelectionList->operator[](1);
	if (secondItem->iUid.iUid != 101)
	{//add
		TBuf<40> buf;
		buf.Copy(Utils::GetR(R_TEXT_SORT_BY_NAME));
		CMySelectableItem* item = CMySelectableItem::NewL(buf, EFalse, TUid::Uid(101));
		iSelectionList->InsertL(1, item);

		buf.Copy(Utils::GetR(R_TEXT_SORT_BY_DATE));
		item = CMySelectableItem::NewL(buf, EFalse, TUid::Uid(102));
		iSelectionList->InsertL(2, item);
	}


	SetSelectionItemArrayL(iSelectionList);
	UpdateListBoxL();
}

void CAppListSettingPage::AddPropertiesStringL(TBool aHidden)
{
	CMySelectableItem* item = CMySelectableItem::NewL(Utils::GetR(R_TEXT_SORT_ORDER), EFalse, TUid::Uid(100));//do not change EFalse, a bug
	iSelectionList->InsertL(0, item);
}

void CAppListSettingPage::HidePropertiesL()
{
	CMySelectableItem* secondItem = (CMySelectableItem*) iSelectionList->operator[](1);
	if (secondItem->iUid.iUid == 101)
	{
		DeleteSelectionListL(1, 2);
	}

	DeleteSelectionListL(0, 1);
	AddPropertiesStringL(ETrue);

	SetSelectionItemArrayL(iSelectionList);
	UpdateListBoxL();
}
void ModifyItem(CDesCArray* aItems, TInt aIndex, const TDesC& aText, TInt aSelected)
{
	TBuf<100> item;
	aItems->Delete(aIndex);
	if (aSelected == -1)
		item.Format(_L("\t\t%S"), &aText);
	else
		item.Format(_L("%d\t%S"), aSelected, &aText);
	aItems->InsertL(aIndex, item);
}

void CAppListSettingPage::UpdateListBoxL()
{
//udpate the radio button	
	CAknSetStyleListBox* listBox = ListBoxControl();

	CFormattedCellListBoxData* columnData = listBox->ItemDrawer()->ColumnData();

	columnData->SetSubCellAlignmentL(2, CGraphicsContext::ERight);


	CDesCArray* items = (CDesCArray*) (listBox->Model()->ItemTextArray());

	TBuf<40> item;
	for (TInt i = 0;i < iSelectionList->Count();i++)
	{
		CMySelectableItem* myItem = (CMySelectableItem*) iSelectionList->operator[](i);
		switch (myItem->iUid.iUid)
		{
			case 100:
			case 200:
			case 201:
			{
				ModifyItem(items, i, myItem->ItemText(), -1);
				break;
			}
			case 101:
			{
				if (iSettings.iAppSortType == TAppListSettings::ESortByName)
					ModifyItem(items, i, myItem->ItemText(), 0);
				else
					ModifyItem(items, i, myItem->ItemText(), 1);
				break;
			}
			case 102:
			{
				if (iSettings.iAppSortType == TAppListSettings::ESortByDate)
					ModifyItem(items, i, myItem->ItemText(), 0);
				else
					ModifyItem(items, i, myItem->ItemText(), 1);
				break;
			}
		}
	}
	listBox->HandleItemAdditionL();
}

void CAppListSettingPage::ConstructL()
{
///	AddPropertiesStringL(ETrue);
	iSettings.LoadSettingsL();
	CAknCheckBoxSettingPage::ConstructL();
//ShowApps
	for (TInt i = 0;i < iAppList->Count();i++)
	{
		iTempAppList.Append((*iAppList)[i]);
	}

	AddApplicationsL();
	UpdateListBoxL();
	if (iSettings.iShowApps)
	{
		ListBoxControl()->SetCurrentItemIndex(2);
	}
	else
		ListBoxControl()->SetCurrentItemIndex(1);
}

TKeyResponse CAppListSettingPage::OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType)
{
	TKeyResponse res = CAknCheckBoxSettingPage::OfferKeyEventL(aKeyEvent, aType);

	switch (aKeyEvent.iCode)
	{
		case EKeyLeftArrow:
		{
			NextPageL(-6);
			break;
		}
		case EKeyRightArrow:
		{
			NextPageL(6);
			break;
		}
		case '0':
		{
			TInt ind = ListBoxControl()->CurrentItemIndex();
			CMySelectableItem* item = (CMySelectableItem*) iSelectionList->operator[](ind);
			CApplicationDetailsDialog::RunDlgLD(item->iUid);
			break;
		}
	}
	return res;
}

void CAppListSettingPage::SelectCurrentItemL()
{
	CAknSetStyleListBox* listBox = ListBoxControl();
	TInt ind = listBox->CurrentItemIndex();
	CMySelectableItem* selItem = (CMySelectableItem*) iSelectionList->operator[](ind);
	switch (selItem->iUid.iUid)
	{
		case 100:
		{//Expand or Shrink properties
			CMySelectableItem* secondItem = (CMySelectableItem*) iSelectionList->operator[](1);
			if (secondItem->iUid.iUid == 101)
			{
				HidePropertiesL();	
			}
			else
			{
				ShowPropertiesL();
			}
			break;
		}
		case 101:
		{
			if (iSettings.iAppSortType != TAppListSettings::ESortByName)
			{
				iSettings.iAppSortType = TAppListSettings::ESortByName;
				iSettings.SaveSettingsL();
				UpdateListBoxL();
				DeleteApplicationsL();
				AddApplicationsL();
			}
			break;
		}
		case 102:
		{
			if (iSettings.iAppSortType != TAppListSettings::ESortByDate)
			{
				iSettings.iAppSortType = TAppListSettings::ESortByDate;
				iSettings.SaveSettingsL();
				UpdateListBoxL();
				DeleteApplicationsL();
				AddApplicationsL();
			}
			break;	
		}
		case 200:
		{//expand or shrink apps
			iSettings.iShowApps = !iSettings.iShowApps;
			iSettings.SaveSettingsL();
			DeleteApplicationsL();
			AddApplicationsL();
			break;
		}
		case 201:
		{
			iSettings.iShowHiddenApps = !iSettings.iShowHiddenApps;
			iSettings.SaveSettingsL();
			DeleteApplicationsL();
			AddApplicationsL();			
			break;
		}
		default:
			CAknCheckBoxSettingPage::SelectCurrentItemL();
			UpdateAppListL(iTempAppList, selItem);
			break;
	}
}

void CAppListSettingPage::DeleteSelectionListL(TInt aStartInd, TInt aCount)
{
	for (TInt i = 0;i < aCount;i++)
	{
		delete iSelectionList->operator[](i+aStartInd);
	}
	iSelectionList->Delete(aStartInd, aCount);
	
}